package 版本1.handle;

import com.alibaba.fastjson2.JSONObject;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.reflections.Reflections;
import org.reflections.scanners.Scanners;
import org.reflections.util.ConfigurationBuilder;
import 版本1.annotation.GetMapping;
import 版本1.annotation.PostMapping;
import 版本1.annotation.RequestMapping;
import 版本1.annotation.RestController;
import 版本1.property.TomcatProperty;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class AopRequestHandler {

    private static final Map<String, Method> routes = new HashMap<>();

    static {
        try {
            scanControllers("controller"); // 调整为你的包路径
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //TODO 待解决，就是我这里其实就是定义了一个假拦截器（本质还是Servlet），但是这里竟然也会注册路径
    private static void scanControllers(String packageName) throws Exception {
        for (Class<?> controller : getClassesInPackage(packageName)) {
            // TODO 确保扫描的类属于指定的包
            //  确保扫描的是controller层的，这样感觉不太后面在细想一下
            if (!controller.getPackage().getName().startsWith(packageName)) {
                continue;
            }

            if (controller.isAnnotationPresent(RestController.class)) {
                String basePath = "";
                if (controller.isAnnotationPresent(RequestMapping.class)) {
                    basePath = controller.getAnnotation(RequestMapping.class).value();
                }

                for (Method method : controller.getDeclaredMethods()) {
                    if (method.isAnnotationPresent(GetMapping.class)) {
                        String fullPath = basePath + method.getAnnotation(GetMapping.class).value();
//                        System.out.println("GET" + fullPath);
                        routes.put("GET" + fullPath, method);
                    } else if (method.isAnnotationPresent(PostMapping.class)) {
                        String fullPath = basePath + method.getAnnotation(PostMapping.class).value();
//                        System.out.println("GET" + fullPath);
                        routes.put("POST" + fullPath, method);
                    }
                }
            }
        }
        System.out.println(routes);
    }

    // 处理请求的方法
    public static void handleRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String method = request.getMethod();
        //这里是存在上下文环境的，就是tomcat中会进行单独配置，所以最好就是把这个放在配置文件中
        //获取对应的处理类的路径
            // 处理上下文路径为空的情况
            //这时候访问：http://localhost:8083/api，上下文环境变为了"/api"
            //如果在tomcat中配置了上下文是正常的
        String relativePath = request.getRequestURI().substring(TomcatProperty.CONTEXT_PATH.length());
        Method handlerMethod = routes.get(method + relativePath);
        System.out.println("Handler Method: " + handlerMethod);
        System.out.println("Requested Method and Path: " + method + " " + relativePath);

        if (handlerMethod != null) {
            try {
                // 调用对应的方法并获取返回值
                handlerMethod.setAccessible(true);
                Object result = handlerMethod.invoke(handlerMethod.getDeclaringClass().newInstance());

                // 统一处理返回值，将返回值转换为JSON并写入响应
                String jsonResponse = JSONObject.toJSONString(result);
                response.setContentType("application/json");
                response.setCharacterEncoding("UTF-8");
                response.getWriter().write(jsonResponse);
            } catch (Exception e) {
                e.printStackTrace();
                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error processing request");
            }
        } else {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, "Route not found");
        }
    }
    private static Set<Class<?>> getClassesInPackage(String packageName) {
        Reflections reflections = new Reflections(new ConfigurationBuilder()
                .forPackages(packageName)//设置包名
                .addScanners(Scanners.TypesAnnotated));//扫描带注解的类型


        Set<Class<?>> controllers = new HashSet<>(reflections.getTypesAnnotatedWith(RestController.class));
        return controllers;
    }
}
